/* ========================================================================= */
/* ------------------------------------------------------------------------- */
/*!
  \file			cpgdoc.cc
  \date			Jan 2013
  \author		TNick

  \brief		Contains the implementation of CpgDoc class


*//*


 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 Please read COPYING and README files in root folder
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
/* ------------------------------------------------------------------------- */
/* ========================================================================= */
//
//
//
//
/*  INCLUDES    ------------------------------------------------------------ */

#include	<QApplication>
#include	<QFileInfo>
#include	<QUrl>
#include	<QDir>
#include	<QVariant>
#include	<QDebug>

#include	<cpg/cpg.h>

#include	"cpgdoc.h"

#include	<cpg/preferences/prefs.h>
#include	<cpg/logic/pglayer.h>
#include	<cpg/logic/layer/pglayglob.h>
#include	<cpg/logic/layer/pglayspc.h>
#include	<cpg/logic/pgspace.h>
#include	<cpg/atoms/pgatomicchg.h>

/*  INCLUDES    ============================================================ */
//
//
//
//
/*  DEFINITIONS    --------------------------------------------------------- */

using namespace cpg;

/*  DEFINITIONS    ========================================================= */
//
//
//
//
/*  DATA    ---------------------------------------------------------------- */

int			CpgDoc::untitled_cnt_ = 1;

/*  DATA    ================================================================ */
//
//
//
//
/*  CLASS    --------------------------------------------------------------- */

/* ------------------------------------------------------------------------- */
CpgDoc::CpgDoc	( bool b_vis, QObject * parent )
	: QObject( parent ), MemTrack()
{
	PGDBG2( PGDBG_CTORDTOR, "Creating CpgDoc", this );
	flg_ = FL_NONE;
	if ( b_vis )
		setHidden();
}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
CpgDoc::~CpgDoc	( void )
{
	PGDBG2( PGDBG_CTORDTOR, "Destroying CpgDoc", this );

	foreach( PgSpace * space, space_lst_ )
	{
		delete space;
	}

	foreach( PgLayGlob * lay, glob_ly_list_ )
	{
		delete lay;
	}
	/** @todo	when blocks are implemented
	foreach( PgBlockDef * blk, blocks_ )
	{
		delete blk;
	}
	*/
}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
bool			CpgDoc::fileNew			( void )
{
	PGDBG2( PGDBG_DOCUMENT, "CpgDoc: new file", this );

	prepareDocument();
	return NULL;
}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
bool			CpgDoc::fileOpen			(
		const QString & f, const QString & loc )
{
	PGDBG2( PGDBG_DOCUMENT, "CpgDoc: open file", this );
	PGDBG2( PGDBG_DOCUMENT, "  - file ", f );

	if ( !QFile::exists(f) )
	{
		PGDBG( PGDBG_DOCUMENT, "  - the file does not exist" );
		return false;
	}

	QFile file( f );
	if ( !file.open( QFile::ReadOnly ) )
	{
		PGDBG( PGDBG_DOCUMENT, "  - error opening file" );
		return false;
	}

	QByteArray data = file.readAll();
	/** @todo interpret file */
	Q_UNUSED( data );

	prepareDocument( f );

	if ( loc.isEmpty() == false )
	{
		PGDBG2( PGDBG_DOCUMENT, "  - going to anchor ", loc );
		/** @todo go to anchor */

	}

	PGDBG( PGDBG_DOCUMENT, "  - file load successfull " );
	return true;
}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
bool			CpgDoc::fileSave			( const QString & f )
{
	PGDBG2( PGDBG_DOCUMENT, "CpgDoc: save file", this );
	PGDBG2( PGDBG_DOCUMENT, "  - file ", f );

	QString	s_file;
	if  (f.isEmpty() )
	{
		PGDBG2( PGDBG_DOCUMENT, "  - defaulting to internal file ", s_file_path_ );
		if ( s_file_path_.isEmpty() )
		{
			PGDBG( PGDBG_DOCUMENT, "  - no internal file specified" );
			return false;
		}
		s_file = s_file_path_;
	}
	else
	{
		s_file = f;
	}

	QFile file( s_file );
	bool success = file.open( QIODevice::WriteOnly );
	if (success)
	{
		PGDBG( PGDBG_DOCUMENT, "  - file was opened" );

		QByteArray data; /** @todo generate the data */
		PGDBG2( PGDBG_DOCUMENT, "  - bytes:", data.length() );

		qint64 c = file.write(data);
		success = (c >= data.length());
		if (success)
		{
			PGDBG( PGDBG_DOCUMENT, "  - file was written" );

			s_file_path_ = s_file;
			s_name_ = QFileInfo( file ).fileName();
			resetReadOnly();
			resetModified();

			emit fileNameModified( s_name_ );
		}
		else
		{
			PGDBG( PGDBG_DOCUMENT, "  - file could not be written" );
		}
	}
	else
	{
		PGDBG( PGDBG_DOCUMENT, "  - file could not be opened" );
	}

	return success;
}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
bool			CpgDoc::openUrl			( const QUrl & url )
{
	PGDBG2( PGDBG_DOCUMENT, "CpgDoc: load url", this );
	PGDBG2( PGDBG_DOCUMENT, "  - path ", url.toString() );

	/** @todo open the url */

	prepareDocument( url.toString(), true );
	return true;
}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
void			CpgDoc::insertText		( const QString & text )
{
	Q_UNUSED( text );
	/** @todo implement  */
}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
void			CpgDoc::prepareDocument	( const QString & file_name, bool is_url )
{
	PGDBG2( PGDBG_DOCUMENT, "CpgDoc: preparing document", this );
	PGDBG2( PGDBG_DOCUMENT, "  - path ", file_name );
	PGDBG2( PGDBG_DOCUMENT, "  - url ", is_url );

	s_file_path_ = file_name;

	if ( file_name.isEmpty() )
	{
		s_name_ = tr( "untitled %1" ).arg( untitled_cnt_ );
		untitled_cnt_++;
	}
	else if ( is_url )
	{
		s_name_ = "";/** @todo open the url */
	}
	else
	{
		s_name_ = QFileInfo( file_name ).fileName();
	}
	PGDBG2( PGDBG_DOCUMENT, "  - deduced name ", s_name_ );

	if ( is_url )
		setReadOnly();
	else
		resetReadOnly();
	resetModified();

	emit fileNameModified( s_name_ );
}
/* ========================================================================= */


/* ------------------------------------------------------------------------- */
QColor			CpgDoc::fillColor				( void )
{
	PGDBG2( PGDBG_DOCUMENT, "CpgDoc: inserting a code box", this );

	/** @todo implement fillColor */

	return QColor();
}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
QColor			CpgDoc::primColor				( void )
{
	PGDBG2( PGDBG_DOCUMENT, "CpgDoc::primColor", this );
	/** @todo implement primColor */

	return QColor();
}
/* ========================================================================= */


/* ------------------------------------------------------------------------- */
bool			CpgDoc::inTable					( void ) const
{
	/** @todo implement inTable */
	bool b = false;
	return b;
}
/* ========================================================================= */


/* ------------------------------------------------------------------------- */
void			CpgDoc::insertTable			( void )
{
	PGDBG2( PGDBG_DOCUMENT, "CpgDoc: inserting a table", this );
	/** @todo implement insertTable */

}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
void			CpgDoc::insertTableCols			( int count )
{
	PGDBG2( PGDBG_DOCUMENT, "CpgDoc: inserting table col(s)", this );
	if ( count <= -1 )
		count = -1;
	/** @todo implement insertTableCols */

}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
void				CpgDoc::removeTableCols			( int count )
{
	PGDBG2( PGDBG_DOCUMENT, "CpgDoc: remove table col(s)", this );
	if ( count < 0 )
		count = 0;
	/** @todo implement removeTableCols */

}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
void				CpgDoc::insertTableRows			( int count )
{
	PGDBG2( PGDBG_DOCUMENT, "CpgDoc: inserting table row(s)", this );
	if ( count <= -1 )
		count = -1;
	/** @todo implement insertTableRows */

}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
void				CpgDoc::removeTableRows			( int count )
{
	PGDBG2( PGDBG_DOCUMENT, "CpgDoc: remove table row(s)", this );
	if ( count < 0 )
		count = 0;
	PGDBG2( PGDBG_DOCUMENT, "  - count", count );
	/** @todo implement removeTableRows */

}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
void				CpgDoc::insertImage				( const QString & s_uri )
{
	PGDBG2( PGDBG_DOCUMENT, "CpgDoc: inserting an image", this );
	Q_UNUSED( s_uri );
	/** @todo implement insertImage */

}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
void				CpgDoc::cut						( void )
{
	/** @todo implement cut */
}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
void				CpgDoc::setFillColor			( const QColor & color )
{
	PGDBG2( PGDBG_DOCUMENT, "CpgDoc: set fill color", this );
	PGDBG2( PGDBG_DOCUMENT, "  - to this", color.name() );


	/** @todo implement setFillColor */

}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
void				CpgDoc::setPrimColor			( const QColor & color )
{
	Q_UNUSED( color );
	/** @todo implement setPrimColor */

}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
void				CpgDoc::findNext				( const QString & s_text )
{
	PGDBG2( PGDBG_DOCUMENT, "CpgDoc: findNext", this );
	PGDBG2( PGDBG_DOCUMENT, "  - find textT", s_text );

	/** @todo implement findNext */

}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
void				CpgDoc::findPrev				( const QString & s_text )
{
	PGDBG2( PGDBG_DOCUMENT, "CpgDoc: findPrev", this );
	PGDBG2( PGDBG_DOCUMENT, "  - find text", s_text );

	/** @todo implement findPrev */


}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
void				CpgDoc::replaceAll				(
		const QString & s_find, const QString & s_repl )
{
	PGDBG2( PGDBG_DOCUMENT, "CpgDoc: replaceAll", this );
	PGDBG2( PGDBG_DOCUMENT, "  - find text", s_find );
	PGDBG2( PGDBG_DOCUMENT, "  - replace text", s_repl );

	/** @todo implement replaceAll */


	/* modified flag is not set by default */
	if ( true )
	{
		emit contentModified();
	}

}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
void				CpgDoc::replaceNext		(
		const QString & s_find, const QString & s_repl )
{
	PGDBG2( PGDBG_DOCUMENT, "CpgDoc: replaceNext", this );
	PGDBG2( PGDBG_DOCUMENT, "  - find text", s_find );
	PGDBG2( PGDBG_DOCUMENT, "  - replace text", s_repl );

	/** @todo implement replaceNext */


	/* modified flag is not set by default */
	if ( true )
	{
		emit contentModified();
	}

}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
void				CpgDoc::replaceOne		(
		const QString & s_find, const QString & s_repl )
{
	PGDBG2( PGDBG_DOCUMENT, "CpgDoc: replaceOne", this );
	PGDBG2( PGDBG_DOCUMENT, "  - find text", s_find );
	PGDBG2( PGDBG_DOCUMENT, "  - replace text", s_repl );

	/** @todo implement replaceOne */


	/* modified flag is not set by default */
	if ( true )
	{
		emit contentModified();
	}

}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
void				CpgDoc::copy			( void )
{
	/** @todo implement copy */

}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
void				CpgDoc::paste			( void )
{
	/** @todo implement paste */

}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
void				CpgDoc::insertHtml		( const QString & content )
{
	Q_UNUSED( content );
	/** @todo implement insertHtml */

}
/* ========================================================================= */


/* ------------------------------------------------------------------------- */
PgLayer *			CpgDoc::layerByName				(
		const QString & s_name ) const
{
	foreach( PgLayer * itr, glob_ly_list_ )	{
		if ( QString::compare( itr->name(), s_name, Qt::CaseInsensitive ) == 0 )
			return itr;
	}
	return NULL;
}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
QString				CpgDoc::layerUniqName			( void ) const
{
	int i;
	QString	s_name;
	for ( i = 0; i < 10000000; i++ )
	{
		s_name = QObject::tr( "GLayer-%1" ).arg( i );
		if ( layerByName( s_name ) == NULL )
		{
			return s_name;
		}
	}
	return s_name;

}
/* ========================================================================= */


/* ------------------------------------------------------------------------- */
void					CpgDoc::layerProps		( int i, LyData & d )
{
	Q_UNUSED( i );
	Q_UNUSED( d );
	/** @todo implement after PgLayData is implemented
	if ( ( i < 0 ) || ( i >= glob_ly_list_.count() ) )
		return;
	glob_ly_list_.at( i )->getData( d );*/
}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
void					CpgDoc::addSpace			( PgSpace * itm )
{
	Q_ASSERT(space_lst_.contains( itm ) == false);
	space_lst_.append( itm );
	if ( crt_space_ == NULL )
	{
		crt_space_ = itm;
	}
	itm->setAssocDoc( this );
}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
PgSpace *				CpgDoc::spaceByName		( const QString & s_name ) const
{
	PgSpace *	iter;
	foreach( iter, space_lst_ )
	{
		if ( QString::compare( s_name, iter->name(), Qt::CaseInsensitive ) == 0 )
		{
			return iter;
		}
	}
	return NULL;
}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
QString					CpgDoc::spaceUniqName	( void )
{
	QString	s_name;
	for( int i = 1; i < 10000000; i++ )
	{
		s_name = QObject::tr( "space-%1").arg( i );
		if ( spaceByName( s_name ) == NULL )
		{
			break;
		}
	}
	return s_name;
}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
void					CpgDoc::remSpace			( PgSpace * itm )
{
	Q_ASSERT(space_lst_.contains( itm ) );
	space_lst_.removeOne( itm );
	if ( crt_space_ == itm )
	{
		if ( space_lst_.count() == 0 )
			crt_space_ = NULL;
		else
			crt_space_ = space_lst_.at( 0 );
	}
}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
bool			CpgDoc::setCurrentSpace			( PgSpace * new_val )
{
	int i = space_lst_.indexOf( new_val );
	if  (i == -1 )
		return false;
	crt_space_ = new_val;

	return true;
}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
void			CpgDoc::addUndoAtom				( AtomicChg * itm )
{
	u_.push( itm );
}
/* ========================================================================= */

/*  CLASS    =============================================================== */
//
//
//
//
/* ------------------------------------------------------------------------- */
/* ========================================================================= */


